import {
  AxiosInstance,
  AxiosResponse,
  AxiosError,
  InternalAxiosRequestConfig,
} from "axios";
import { Response } from "./model";
import { getAxiosBaseConfig } from "./config";
import { Dialog } from "antd-mobile";

/**
 * 设置拦截器
 * @param instance axios实例
 */
export const setupInterceptors = (instance: AxiosInstance): void => {
  const axiosBaseConfig = getAxiosBaseConfig();
  // 请求拦截器
  instance.interceptors.request.use(
    async (config: InternalAxiosRequestConfig) => {
      // 从存储中获取token
      const token = localStorage.getItem(
        axiosBaseConfig.authTokenName as string
      );
      if (token && config.headers) {
        config.headers.set(axiosBaseConfig.authTokenName, token);
      }

      return config;
    },
    (error: AxiosError) => {
      console.log("请求错误拦截器:", error);
      return Promise.reject(error);
    }
  );

  // 响应拦截器
  let timer: number | null = null;
  let isDefaultOpenErrorHandle = true;
  const defaultErrorHandler = (
    response: AxiosError | AxiosResponse<Response<any>>
  ) => {
    const hiddenDefaultErrorHandler = () => (isDefaultOpenErrorHandle = false);
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      if (!isDefaultOpenErrorHandle) return;
      if (response.status != 200) {
        return Dialog.alert({
          content: "服务器错误，请稍后再试",
          onConfirm: () => {
            return;
          },
        });
      }
      switch ((response as AxiosResponse<Response<any>>).data.code) {
        case 401:
          axiosBaseConfig.authFailed!();
          break;
        default:
          Dialog.alert({
            content:
              (response as AxiosResponse<Response<any>>).data[
                axiosBaseConfig.messageName as keyof Response<any>
              ] ?? "服务器未知错误，请稍后",
            onConfirm: () => {
              console.log("Confirmed");
            },
          });
      }
    }, 0);
    return hiddenDefaultErrorHandler;
  };
  instance.interceptors.response.use(
    (response: AxiosResponse<Response<any>>) => {
      if (response.config.responseType === "blob") {
        return response;
      } else {
        switch (response.data?.code) {
          case axiosBaseConfig.successNetworkCode:
            return response.data?.data;
          default:
            const hiddenDefaultErrorHandler = defaultErrorHandler(response);
            throw {
              ...response,
              hiddenDefaultErrorHandler,
              uri: instance.getUri(),
            };
        }
      }
    },
    (error: AxiosError) => {
      const hiddenDefaultErrorHandler = defaultErrorHandler(error);
      throw { ...error, hiddenDefaultErrorHandler, uri: instance.getUri() };
    }
  );
};
